#include<iostream>
using namespace std;
template<typename T1,typename T2>
class person;


//注意该函数为全局函数，就不用写作用域了（成员函数才用写）
template<typename T1, typename T2>
void printperson2<>(person<T1, T2>p)//因为这里会用到person,所以要提前声明person
{
	cout << "name=" << p.m_age << "age=" << p.m_age << endl;
}
//printPerson2<>()的声明是定义Person类里面的，编译器无法直接看到，因此，我们还要在类外进行再次声明
//类内添加友元函数后，如果没有对该友元函数进行声明，编译器认为你没有这个函数，会进行报错。




//
template<typename T1,typename T2>
class person
{
public:
	//全局函数在类模板的类内实现
	friend void printperson1(person<T1,T2>p)
	{
		cout << "name=" << p.m_age << "age=" << p.m_age << endl;
	}
	//全局函数在类模板的类外实现（在类内只写申明，在类外写实现）
	//friend void printperson2(person<T1, T2>);//错误写法
/*
    编译的时候报了一个错误，: 1 个无法解析的外部命令。

现在我们就来分析这个错误，首先说谁无法被解析，答案是printPerson()，编译器无法找到printPerson2()的函数实现，看到这里，你可能会有疑问
，我明明已经在类外实现了printPerson2()这个函数，为什么还无法被解析。原因是：printPerson2()在Person中被声明了为普通函数，
因为就会将printPerson2()作为普通函数调用那样对待，然后就会去寻找它的实现实体，很明显模板函数只有在程序运行的时候才会被创建，
自然无法找到它的实体，因此就报了这个无法解析的外部命令这个错误。要解决这个错误很简单，我们只要在将printPerson()作为模板函数调用就行了
只需要在声明printPerson2时，添加一个<>，表名它是模板调用就行了、*/
friend void printperson2(person<T1, T2>);
	//友元函数类内实现  利用空参数列表 告诉编译器 模板函数的声明


	person(T1 name, T2 age)
	{
		this->m_age = age;
		this->m_name = name;
	}
private:
	T1 m_name;
	T2 m_age;
};

void test01()
{
	person<string, int>p("李华", 18);
	printperson1(p);
}
int main(void)
{
	test01();
	system("pause");
}

//还有一种写法。把printperson2提前声明和定义拆分开

#include<iostream>
using namespace std;
template<typename T1,typename T2>
class person;


//注意该函数为全局函数，就不用写作用域了（成员函数才用写）
template<typename T1, typename T2>
void printperson2<>(person<T1, T2>p);//因为这里会用到person,所以要提前声明person

//类内添加友元函数后，如果没有对该友元函数进行声明，编译器认为你没有这个函数，会进行报错。


//
template<typename T1,typename T2>
class person
{
public:
	//全局函数在类模板的类内实现
	friend void printperson1(person<T1,T2>p)
	{
		cout << "name=" << p.m_age << "age=" << p.m_age << endl;
	}
	//全局函数在类模板的类外实现（在类内只写申明，在类外写实现）
	friend void printperson2(person<T1, T2>);
	person(T1 name, T2 age)
	{
		this->m_age = age;
		this->m_name = name;
	}
private:
	T1 m_name;
	T2 m_age;
};

template<typename T1, typename T2>
void printperson2(person<T1, T2>p)//因为这里会用到person,所以要提前声明person
{
	cout << "name=" << p.m_age << "age=" << p.m_age << endl;
}

void test01()
{
	person<string, int>p("李华", 18);
	printperson1(p);
}
int main(void)
{
	test01();
	system("pause");
}